<!DOCTYPE html>

<html lang="zh-CN">

<head>
  
  <title>Servlet - lingqu&#39;blog</title>
  <meta charset="UTF-8">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
  
  

  <link rel="shortcut icon" href="/favicon.ico" type="image/png" />
  <meta name="description" content="这里是学习Servlet时的一些笔记整理">
<meta property="og:type" content="article">
<meta property="og:title" content="Servlet">
<meta property="og:url" content="https://lingqu.github.io/2021/06/10/Servlet/index.html">
<meta property="og:site_name" content="lingqu&#39;blog">
<meta property="og:description" content="这里是学习Servlet时的一些笔记整理">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-06-10T14:11:02.000Z">
<meta property="article:modified_time" content="2021-06-10T14:14:11.819Z">
<meta property="article:author" content="lingqu">
<meta name="twitter:card" content="summary">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/npm/highlight.js@9.15.8/styles/atom-one-dark.css,npm/justifiedGallery@3.8.1/dist/css/justifiedGallery.min.css,gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css,npm/hexo-theme-nexmoe@latest/source/lib/mdui_043tiny/css/mdui.css,npm/hexo-theme-nexmoe@latest/source/lib/iconfont/iconfont.css?v=233" crossorigin>
  <link rel="stylesheet" href="/css/style.css?v=1629344957172">
  
  <link rel="stylesheet" href="/css/style.css?v=1629344957172">
  <link rel="stylesheet" href="/lib/iconfont/iconfont.css?v=1629344957172">
<meta name="generator" content="Hexo 5.4.0"></head>

<body class="mdui-drawer-body-left">
  
  <div id="nexmoe-background">
    <div class="nexmoe-bg" style="background-image: url(http://pic1.win4000.com/wallpaper/f/5922779a761cd.jpg)"></div>
    <div class="mdui-appbar mdui-shadow-0">
      <div class="mdui-toolbar">
        <a mdui-drawer="{target: '#drawer', swipe: true}" title="menu" class="mdui-btn mdui-btn-icon mdui-ripple"><i class="mdui-icon nexmoefont icon-menu"></i></a>
        <div class="mdui-toolbar-spacer"></div>
        <!--<a href="javascript:;" class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">search</i></a>-->
        <a href="/" title="lingqu" class="mdui-btn mdui-btn-icon"><img src="https://inews.gtimg.com/newsapp_bt/0/13492515314/1000" alt="lingqu"></a>
       </div>
    </div>
  </div>
  <div id="nexmoe-header">
      <div class="nexmoe-drawer mdui-drawer" id="drawer">
    <div class="nexmoe-avatar mdui-ripple">
        <a href="/" title="lingqu">
            <img src="https://inews.gtimg.com/newsapp_bt/0/13492515314/1000" alt="lingqu" alt="lingqu">
        </a>
    </div>
    <div class="nexmoe-count">
        <div><span>文章</span>8</div>
        <div><span>标签</span>3</div>
        <div><span>分类</span>0</div>
    </div>
    <div class="nexmoe-list mdui-list" mdui-collapse="{accordion: true}">
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/" title="回到首页">
            <i class="mdui-list-item-icon nexmoefont icon-home"></i>
            <div class="mdui-list-item-content">
                回到首页
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/about.html" title="关于博客">
            <i class="mdui-list-item-icon nexmoefont icon-info-circle"></i>
            <div class="mdui-list-item-content">
                关于博客
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/PY.html" title="我的朋友">
            <i class="mdui-list-item-icon nexmoefont icon-unorderedlist"></i>
            <div class="mdui-list-item-content">
                我的朋友
            </div>
        </a>
        
    </div>
    <aside id="nexmoe-sidebar">
  
  <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-search">
        <form id="search_form" action_e="https://cn.bing.com/search?q=site:nexmoe.com" onsubmit="return search();">
            <label><input id="search_value" name="q" type="search" placeholder="搜索"></label>
        </form>
    </div>
</div>
  
  <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-social">
        <a class="mdui-ripple" href="https://jq.qq.com/?_wv=1027&k=5CfKHun" target="_blank" mdui-tooltip="{content: 'QQ群'}" style="color: rgb(249, 174, 8);background-color: rgba(249, 174, 8, .1);">
            <i class="nexmoefont icon-QQ"></i>
        </a><a class="mdui-ripple" href="https://space.bilibili.com/51207190" target="_blank" mdui-tooltip="{content: '哔哩哔哩'}" style="color: rgb(231, 106, 141);background-color: rgba(231, 106, 141, .15);">
            <i class="nexmoefont icon-bilibili"></i>
        </a><a class="mdui-ripple" href="https://github.com/lingqu/" target="_blank" mdui-tooltip="{content: 'GitHub'}" style="color: rgb(25, 23, 23);background-color: rgba(25, 23, 23, .15);">
            <i class="nexmoefont icon-github"></i>
        </a>
    </div>
</div>
  
  

  
  
  <div class="nexmoe-widget-wrap">
    <div id="randomtagcloud" class="nexmoe-widget tagcloud nexmoe-rainbow">
      <a href="/tags/C/" style="font-size: 20px;">C++</a> <a href="/tags/JavaScript/" style="font-size: 10px;">JavaScript</a> <a href="/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 20px;">数据结构</a>
    </div>
    
  </div>

  
</aside>
    <div class="nexmoe-copyright">
        &copy; 2021 lingqu
        Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
        & <a href="https://github.com/theme-nexmoe/hexo-theme-nexmoe" target="_blank">Nexmoe</a>
        
    </div>
</div><!-- .nexmoe-drawer -->
  </div>
  <div id="nexmoe-content">
    <div class="nexmoe-primary">
        <div class="nexmoe-post">

  <article>
    
        <div class="nexmoe-post-cover" style="padding-bottom: 45.83333333333333%;"> 
            <img data-src="http://pic1.win4000.com/wallpaper/f/5922779a761cd.jpg" data-sizes="auto" alt="Servlet" class="lazyload">
            <h1>Servlet</h1>
        </div>
    
    
    <div class="nexmoe-post-meta nexmoe-rainbow" style="margin:10px 0!important;">
    <a><i class="nexmoefont icon-calendar-fill"></i>2021年06月10日</a>
    <a><i class="nexmoefont icon-areachart"></i>4,288 字</a>
    <a><i class="nexmoefont icon-time-circle-fill"></i>大概 17 分钟</a>
</div>

    

    <p>这里是学习Servlet时的一些笔记整理</p>
<span id="more"></span>
<h1 id="Servlet"><a href="#Servlet" class="headerlink" title="Servlet"></a>Servlet</h1><h2 id="HttpServletRequest对象"><a href="#HttpServletRequest对象" class="headerlink" title="HttpServletRequest对象"></a>HttpServletRequest对象</h2><h3 id="常用方法"><a href="#常用方法" class="headerlink" title="常用方法"></a>常用方法</h3><table>
<thead>
<tr>
<th>方法</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>getRequestURL()</td>
<td>获取客服端发出请求时的完整URL</td>
</tr>
<tr>
<td>getRequestURI()</td>
<td>获取请求行中的资源名称部分（项目名称开始）</td>
</tr>
<tr>
<td>getQueryString()</td>
<td>获取请求行中的参数部分</td>
</tr>
<tr>
<td>getMethod()</td>
<td>获取客服端请求方式</td>
</tr>
<tr>
<td>getProtocol()</td>
<td>获取HTTP版本号</td>
</tr>
<tr>
<td>getContextPath()</td>
<td>获取webapp名字(/+当前项目的名字)</td>
</tr>
<tr>
<td>getParameter()</td>
<td>获取指定名称参数,返回字符串（重点）</td>
</tr>
<tr>
<td>getParameterValues()</td>
<td>获取指定名称参数,返回字符串组</td>
</tr>
</tbody></table>
<pre><code class="java">//获取完整路径
StringBuffer URL=request.getRequestURL();
System.out.println(&quot;URL: &quot; + URL);
//获取请求时的部分路径
String URI=request.getRequestURI();
System.out.println(&quot;URI: &quot; + URI);
//获取请求时的参数字符串
String queryString=request.getQueryString();
System.out.println(&quot;queryString: &quot; + queryString);
//获取请求方式（GET和POST）
String method=request.getMethod();
System.out.println(&quot;method: &quot; + method);
//获取当前协议版本（HTTP/1.1）
String protocol =request.getProtocol();
System.out.println(&quot;protocol: &quot;+protocol);
//获取项目站点名
String webapp=request.getContextPath();
System.out.println(&quot;webapp: &quot;+webapp);

//获取指定名称参数,返回字符串
String name = request.getParameter(&quot;name&quot;);
String pwd = request.getParameter(&quot;pwd&quot;);
System.out.println(&quot;name: &quot; +name+&quot; pwd: &quot;+pwd);
//获取指定名称参数,返回字符串组
String[] hobbys = request.getParameterValues(&quot;hobby&quot;);
//判断是否为空
if(hobbys!=null&amp;&amp;hobbys.length!=0)&#123;
    for(String hobby: hobbys)&#123;
         System.out.println(&quot;爱好: &quot;+hobby);
    &#125; 
&#125;
</code></pre>
<h3 id="请求乱码问题"><a href="#请求乱码问题" class="headerlink" title="请求乱码问题"></a>请求乱码问题</h3><p>tomcat 8以上版本：</p>
<p>​                                    GET请求：不会乱码</p>
<p>​                                    POST请求：会乱码    用 <code>request.setCharacterEncoding(&quot;UTF-8&quot;);</code></p>
<p>tomacat 7以下版本：</p>
<p>​                                    POST请求：会乱码    用 <code>request.setCharacterEncoding(&quot;UTF-8&quot;);</code>   //只对7的post有效</p>
<p>​                                    GET请求：会乱码      用<code>new String (request.getParameter(&quot;name&quot;).getBytes(&quot;ISO-8859-1&quot;),&quot;UTF-8“) </code>  //而8以上不乱码使用后乱码                                                                    </p>
<h4 id="方式一"><a href="#方式一" class="headerlink" title="方式一"></a>方式一</h4><pre><code class="java">request.setCharacterEncoding(&quot;UTF-8&quot;);
</code></pre>
<h4 id="方式二"><a href="#方式二" class="headerlink" title="方式二"></a>方式二</h4><pre><code class="java">new String (request.getParameter(&quot;name&quot;).getBytes(&quot;ISO-8859-1&quot;),&quot;UTF-8&quot;) 
</code></pre>
<h3 id="请求转发"><a href="#请求转发" class="headerlink" title="请求转发"></a>请求转发</h3><p>1.一种服务器行为，2.地址栏URL地址不变，3.从始至终只有一个请求发出，4.数据共享（后台跳前台）</p>
<pre><code class="java">request.getRequestDispatcher(url).forward(request,response);
</code></pre>
<h3 id="request作用域"><a href="#request作用域" class="headerlink" title="request作用域"></a>request作用域</h3><p>通过该对象可以在一次请求中传递数据，作用范围：在一次请求中有效，即服务器跳转有效.</p>
<p>可以在请求转发中使用，一个设置另一个获取</p>
<pre><code class="java">//设置域对象内容
request.setAttrivute(String name,Object value);
//获取域对象内容
request.getAttribut(String name);
//删除域对象内容
request.removeAttribute(String name);
</code></pre>
<h2 id="HttpServletResponse对象"><a href="#HttpServletResponse对象" class="headerlink" title="HttpServletResponse对象"></a>HttpServletResponse对象</h2><p>HttpServletResponse主要功能用于服务器对客户端的请求进行响应，将web服务器处理后的结果返回给客户端。</p>
<h3 id="响应数据"><a href="#响应数据" class="headerlink" title="响应数据"></a>响应数据</h3><p>响应时需要获取输出流，有两种形式（两种不能同时使用）：</p>
<pre><code class="java">getWriter()//获取字符流（只能响应回字符）
getOutputStream()//获取字节流（能响应一切数据）
</code></pre>
<pre><code class="java">//字符输出流
PrintWriter writer=response.getwriter();
writer.write(&quot;hello&quot;);
//或者 writer.println(&quot;hello&quot;);
writer.write(&quot;&lt;h2&gt;hello&lt;/h2&gt;&quot;);
</code></pre>
<pre><code class="java">//字节输出流
ServletOUtputStream out = response.getOutputStream();
out.write(&quot;Hello&quot;.getBytes());
out.write(&quot;&lt;h2&gt;Hello&lt;/h2&gt;&quot;.getBytes());
</code></pre>
<h3 id="响应乱码问题"><a href="#响应乱码问题" class="headerlink" title="响应乱码问题"></a>响应乱码问题</h3><pre><code class="java">//设置服务端的编码格式
response.setCharacterEncoding(&quot;UTF-8&quot;);
//设置客户端的编码格式
response.setHeader(&quot;content-type&quot;,&quot;text/html;charset=UTF-8&quot;)
</code></pre>
<p>设置客户端和服务端的编码格式，且保持一致</p>
<pre><code class="java">//同时设置客户端和服务端的编码格式
response.setContentType(&quot;text/html;charset=UTF-8&quot;);
</code></pre>
<p>第二种方法好一点。</p>
<p>注：编码格式要在所有输出流前面设置，如果设置编码格式前面有一个输出都会导致编码格式设置失效</p>
<h3 id="重定向"><a href="#重定向" class="headerlink" title="重定向"></a>重定向</h3><p>1.是一种服务端指导客户端行为，2.存在两次请求，3.地址栏会改变，4.request对象不共享</p>
<pre><code class="java">//重定向到index.jsp
response.sendRedirect(&quot;index.jsp&quot;);
</code></pre>
<h4 id="重定向与请求转发的区别"><a href="#重定向与请求转发的区别" class="headerlink" title="重定向与请求转发的区别"></a>重定向与请求转发的区别</h4><table>
<thead>
<tr>
<th align="left">请求转发 [ request.getRequestDispatcher().forward() ]</th>
<th>重定向 [ response.sendRedirect() ]</th>
</tr>
</thead>
<tbody><tr>
<td align="left">一次请求，数据在request域中共享</td>
<td>两次请求，request域中数据不共享</td>
</tr>
<tr>
<td align="left">服务端行为</td>
<td>客户端行为</td>
</tr>
<tr>
<td align="left">地址栏不发生改变</td>
<td>地址栏发生改变</td>
</tr>
<tr>
<td align="left">绝对地址定位到站点后（只能到当前站点下）</td>
<td>绝对地址可写到http://</td>
</tr>
</tbody></table>
<h2 id="Cookie对象"><a href="#Cookie对象" class="headerlink" title="Cookie对象"></a>Cookie对象</h2><p>浏览器的一种技术，通过服务器的程序能将一些只须保存在客户端，或者客户端进行处理的数据，放在本地计算机上，提高网页的处理效率，但由于是服务端保持客户端的信息，所有安全性很差（浏览器记者密码）。</p>
<h3 id="Cooike的创建和发送"><a href="#Cooike的创建和发送" class="headerlink" title="Cooike的创建和发送"></a>Cooike的创建和发送</h3><p>通过<code>new Cookie(&quot;key&quot;,&quot;value&quot;);</code>来创建对象，要响应发到客户端，需先添加到response对象中，<code>response.addCookie(cookie);</code>此时cookie对象则随着响应发送至客户端</p>
<pre><code class="java">//创建Cookie对象
Cookie cookie = new Cookie(&quot;uame&quot;,&quot;lingqu&quot;);
//发送Cookie对象
response.addCookie(cookie);
</code></pre>
<h3 id="Cookie的获取"><a href="#Cookie的获取" class="headerlink" title="Cookie的获取"></a>Cookie的获取</h3><p>用<code>getCookie()</code>方法获取返回的是cookie数组，获取单个需要遍历，<code>getName()</code>获取Cookie的名称，<code>getValue()</code>获取Cookie的值。</p>
<pre><code class="java">//获取Cookie数组
Cookie[] cookies = request.getCookies();
//判断数组是否为空
if(cookies != null &amp;&amp; cookies.length &gt; 0)&#123;
    //遍历数组
    for(Cookie cookie : cookies)&#123;
        System.out.println(cookie.getName());
        System.out.println(cookie.getValue());
    &#125;
&#125;
</code></pre>
<h3 id="Cookie设置到期时间"><a href="#Cookie设置到期时间" class="headerlink" title="Cookie设置到期时间"></a>Cookie设置到期时间</h3><p>我们可以手动设定cookie的有效时间，通过<code>setMaxAge(int time);</code>方法设定cookie的最大有效时间，单位(秒).</p>
<h4 id="到期时间的取值"><a href="#到期时间的取值" class="headerlink" title="到期时间的取值"></a>到期时间的取值</h4><ul>
<li><p>负整数</p>
<p>表示不储存cookie。maxAge的默认值就是-1，表示只在浏览器内存中存活，关闭浏览器，cookie会消失</p>
</li>
<li><p>正整数</p>
<p>表示cookie可储存的秒数。大于0时，会把cookie保存到硬盘上，关闭浏览器，重启客户端电脑，cookie也存活相应的时间</p>
</li>
<li><p>零</p>
<p>表示删除该cookie。无论在浏览器内存中还是客户端硬盘上都会删除这个cookie。</p>
</li>
</ul>
<h3 id="Cookie的路径"><a href="#Cookie的路径" class="headerlink" title="Cookie的路径"></a>Cookie的路径</h3><p>​     <code>setPath</code>设置cookie路径，路径直接决定服务器的请求是否会从浏览器中加载某些cookie。</p>
<ul>
<li><p>服务器任何项目的任意资源都可获取Cookie对象</p>
<pre><code class="java">//当前项目路径为：s01
Cookie cookie = new Cookie(&quot;xxx&quot;,&quot;xxx&quot;);
//设置路径为&quot;/&quot;,表示在当前服务器下任何项目都可访问到Cookie对象
cookie.setPath(&quot;/&quot;);
response.addCookie(cookie);
</code></pre>
</li>
<li><p>当前项目下的资源可获取Cookie对象</p>
<pre><code class="java">//当前项目路径为：s01
Cookie cookie = new Cookie(&quot;xxx&quot;,&quot;xxx&quot;);
//设置路径为&quot;/s01&quot;,表示在当前项目下任何项目都可访问到Cookie对象
cookie.setPath(&quot;/s01&quot;);//默认情况，可不设置path的值
response.addCookie(cookie);
</code></pre>
</li>
<li><p>指定项目下的资源可获取Cookie对象</p>
<pre><code class="java">//当前项目路径为：s01
Cookie cookie = new Cookie(&quot;xxx&quot;,&quot;xxx&quot;);
//设置路径为&quot;/s02&quot;,表示在s02项目下才可访问到Cookie对象
cookie.setPath(&quot;/s02&quot;);//只能在s02项目下获取Cookie，就算cookie是s01产生的，s01也不能获取它
response.addCookie(cookie);
</code></pre>
</li>
<li><p>指定目录下的资源可获取Cookie对象</p>
<pre><code class="java">//当前项目路径为：s01
Cookie cookie = new Cookie(&quot;xxx&quot;,&quot;xxx&quot;);
//设置路径为&quot;/s01/cook&quot;,表示在s01/cook目录下才可访问到Cookie对象
cookie.setPath(&quot;/s01/cook&quot;);
response.addCookie(cookie);
</code></pre>
</li>
</ul>
<p>注：当访问的路径包含了cookie的路径时，则该请求将带上该cookie；如果访问路径不包含cookie路径，则该请求不会携带该cookie。</p>
<h2 id="HttpSession对象"><a href="#HttpSession对象" class="headerlink" title="HttpSession对象"></a>HttpSession对象</h2><p>每个客户端都是一个session。Session的作用就是为了标记一次会话，或者确认一个用户；并且在一次会话（一个用户的多次请求）期间共享数据。我们可以通过<code>request.getSession()</code>方法，来获取当前会话session对象。</p>
<p>当获取session对象时，会先判断session对象是否存在，如果存在，则获取session对象；如果不存在，就创建session对象</p>
<pre><code class="java">//获取session对象
HttpSession session = request.getSession();
//获取session会话标识符
String id = session.getId();
System.out.println(id);
//获取session的创建时间
System.out.println(session.getCreationTime());
//获取最后一次访问时间
System.out.println(session.getLastAccessedTime());
//判断是否是新的session对象
System.out.println(session.isNew());
</code></pre>
<h3 id="标识符JSESSIONID"><a href="#标识符JSESSIONID" class="headerlink" title="标识符JSESSIONID"></a>标识符JSESSIONID</h3><p>​        每当一次请求到达服务器，如果开启了会话(访问了session)，服务器第一步会查看是否从客户端回传一个名为JSESSIONID的cookie，如果没有则认为这是一次新的会话，会创建一个新的session对象，并用唯一的sessionld为此次会话做一个标志。如果有JESSIONID这个cookie回传，服务器则会根据JSESSIONID这个值去查看是否含有id为]SESSION值的session对象，如果没有则认为是一个新的会话，重新创建一个新的session对象，并标志此次会话;如果找到了相应的session对象，则认为是之前标志过的一次会话，返回该session对象，数据达到共享。<br>​        这里提到一个叫做JSESSIONID的cookie，这是一个比较特殊的cookie，当用户请求服务器时，如果访问了sessionI则服务器会创建一个名为JSESSIONID，值为获取到的session (无论是获取到的还是新创建的)的sessionld的cookie对象，并添加到 response对象中，响应给客户端，有效时间为关闭浏览器。<br>​        所以Session的底层依赖Cookie来实现。</p>
<h3 id="session域对象"><a href="#session域对象" class="headerlink" title="session域对象"></a>session域对象</h3><p>Session用来表示一次会话，在一次会话中数据是可以共享的，这时session作为域对象存在，可以通过<code>setAttribute(name,value)</code>方法向域对象中添加数据，通过<code>getAttribute(name)</code>从域对象中获取数据，通过<code>removeAttribute(name)</code>从域对象中移除数据。</p>
<pre><code class="java">//获取Session对象
HttpSession session = request.getSession();

//设置session域对象
session.setAttribute(&quot;uname&quot;,&quot;admin&quot;);
session.setAttribute(&quot;upwd&quot;,&quot;123456&quot;);

//移除session对象
session.removeAttribute(&quot;upwd&quot;);

//request对象
request.setAttribute(&quot;name&quot;,&quot;zhangsan&quot;);

//请求转发到jsp页面(Session对象和request对象都可以传值)
//req.getRequestDispatcher(&quot;index.jsp&quot;).forward(req,resp);
//重定向到jsp页面(Session可以传值)
response.sendRedirect(&quot;index.jsp&quot;);
</code></pre>
<h3 id="Session对象的销毁"><a href="#Session对象的销毁" class="headerlink" title="Session对象的销毁"></a>Session对象的销毁</h3><ul>
<li><p>默认时间到期</p>
<p>tomcat中session默认存活时间为30min，即你不操作界面的时间，一旦有操作，session会重新计时</p>
<pre><code class="java">//默认的最大不活动时间，单位（分钟）
&lt;session-config&gt;
    &lt;session-timeout&gt;30&lt;/session-timeout&gt;
&lt;/session-config&gt;
</code></pre>
</li>
<li><p>自己设定到期时间</p>
<p>通过<code>session.setMaxInactiveInterval(int)</code>来设置session的最大不活动时间，单位（秒）。</p>
<pre><code class="java">//获取session对象
HttpSession session = request.getSession();
//获取最大不活动时间
session.getMaxInactiveInterval();
//设置session的最大不活动时间
session.setMaxInactiveInterval(15);  //15秒
</code></pre>
</li>
<li><p>立即销毁</p>
<p>可以通过<code>session.invalidate()</code>方法让session立刻失效</p>
<pre><code class="java">//销毁session对象
session.invalidate();
</code></pre>
</li>
<li><p>关闭浏览器</p>
<p>从前面的JESSIONID可知道,session的底层依赖cookie实现，并且该cookie的有效时间为关闭浏览器，从而session在浏览器关闭时也相当于失效了(因为没有JSESSION再与之对应)。</p>
</li>
<li><p>关闭服务器</p>
<p>当关闭服务器时，session 销毁。Session失效则意味着此次会话结束，数据共享结束。</p>
</li>
</ul>
<h2 id="ServletContext对象"><a href="#ServletContext对象" class="headerlink" title="ServletContext对象"></a>ServletContext对象</h2><p>每一个web应用都有且仅有一个ServletContext对象，又称Application对象，从名称中可知，该对象是与应用程序相关的。在WEB容器启动的时候，会为每一个WEB应用程序创建一个对应的ServletContext对象。</p>
<p>该对象有两大作用，第一、作为域对象用来共享数据，此时数据在整个应用程序中共享;第二、该对象中保存了当前应用程序相关信息。例如可以通过<code>getServerInfo()</code>方法获取当前服务器信息，<code>getRealPath(Stringpath)</code>获取资源的真实路径等。</p>
<h3 id="ServletContext对象的获取"><a href="#ServletContext对象的获取" class="headerlink" title="ServletContext对象的获取"></a>ServletContext对象的获取</h3><p> 获取ServletContext对象的途径有很多。比如:</p>
<ul>
<li><p>通过request对象获取</p>
<pre><code class="java">ServletContext servletContext = request.getServletContext() ;
</code></pre>
</li>
<li><p>通过session对象获取</p>
<pre><code class="java">ServletContext servletContext = request.getSession(). getservletContext();
</code></pre>
</li>
<li><p>通过servletConfig 对象获取在Servlet标准中提供了ServletConfig 方法</p>
<pre><code class="java">ServletContext servletContext3 = getServletConfig().getServletContext();
</code></pre>
</li>
<li><p>直接获取</p>
<pre><code class="java">ServletContext servletContext4 = getServletContext();
</code></pre>
</li>
<li><p>常用方法</p>
<pre><code class="java">//1、获取当前服务器的版本信息
String servletInfo = request.getServletContext().getServerInfo();
System.out.println(&quot;当前服务器的版本信息: &quot;+ servletInfo);
//获取项目真实路径
String realPath = request.getServletContext().getRealPath(&quot;/&quot;);
System.out.println(&quot;项目真实路径: &quot;+realPath);
</code></pre>
</li>
</ul>
<h3 id="ServletContext域对象"><a href="#ServletContext域对象" class="headerlink" title="ServletContext域对象"></a>ServletContext域对象</h3><p>ServletContext 也可当做域对象来使用，通过向ServletContext 中存取数据，可以使得整个应用程序共享某些数据。当然不建议存放过多数据，因为ServletContext 中的数据一旦存储进去没有手动移除将会一直保存。</p>
<pre><code class="java">//获取servletcontext对象
ServletContext servletContext = request.getServletContext();

//设置域对象
servletContext.setAttribute(&quot;name&quot; , &quot;zhangsan&quot;) ;
/获取域对象
String uname = (String) servletContext.getAttribute(&quot;name&quot;) ;
//移除域对象
servletContext.removeAttribute(&quot;uname&quot;) ;
</code></pre>
<h4 id="Servlet的三大域对象"><a href="#Servlet的三大域对象" class="headerlink" title="Servlet的三大域对象"></a>Servlet的三大域对象</h4><h5 id="request域对象"><a href="#request域对象" class="headerlink" title="request域对象"></a>request域对象</h5><p>在一次请求中有效。请求转发有效，重定向失效。</p>
<h5 id="session域对象-1"><a href="#session域对象-1" class="headerlink" title="session域对象"></a>session域对象</h5><p>在一次会话中有效。请求转发和重定向都有效，session销毁后失效。</p>
<h5 id="servletContext域对象"><a href="#servletContext域对象" class="headerlink" title="servletContext域对象"></a>servletContext域对象</h5><p>在整个应用程序中有效。服务器关闭后失效。</p>
<h2 id="文件的上传和下载"><a href="#文件的上传和下载" class="headerlink" title="文件的上传和下载"></a>文件的上传和下载</h2><h3 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h3><h4 id="前台页面"><a href="#前台页面" class="headerlink" title="前台页面"></a>前台页面</h4><p>在做文件上传的时候，会有一个上传文件的界面，首先我们需要一个表单，并且表单的请求方式为POST;其次我们的form表单的enctype必须设为”multipart/form-data”，即<code>enctype=&quot;multipart/form-data&quot;</code>，意思是设置表单的类型为文件上传表单。默认情况下这个表单类型是<code>&quot;application/x-www-form-urlencoded&quot;</code>,不能用于文件上传。只有使用了<code>multipart/form-data </code>才能完整地传递文件数据。</p>
<pre><code class="html">&lt;!--
文件上传表单
    1．表单提交类型method=&quot;post&quot;
    2．表单类型enctype=&quot;multipart/form-data&quot;
    3．表单元素类型文件域设置name属性值
--&gt;
&lt;form method=&quot;post&quot; action=&quot;uploadServlet&quot; enctype=&quot;multipart/form-data&quot;&gt;
    姓名: &lt;input type=&quot;text&quot; name=&quot;uname&quot; &gt; &lt;br&gt;
    文件: &lt;input type=&quot;file&quot; name=&quot;myfile&quot; &gt; &lt;br&gt;
    &lt;button type=&quot;submit&quot;&gt;提交&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<h4 id="后台设置"><a href="#后台设置" class="headerlink" title="后台设置"></a>后台设置</h4><p>使用注解<code>@MultipartConfig</code>将一个Servlet标识为支持文件上传。Servlet将 <code>multipart/form-data</code>的POST请求封装成Part，通过Part对上传的文件进行操作。</p>
<pre><code class="java">package Context;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
@WebServlet(&quot;/uploadServlet&quot;)
@MultipartConfig   //如果是文件上次必须加
public class Servlet extends HttpServlet &#123;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
        System.out.println(&quot;文件上传...&quot;);
        //设置请求编码
        request.setCharacterEncoding(&quot;UTF-8&quot;);
        //获取普通参数
        String name = request.getParameter(&quot;uname&quot;);
        System.out.println(&quot;uname: &quot;+name);

        //获取part文件
        Part part = request.getPart(&quot;myfile&quot;);//表单中文件的属性值
        //通过part对象得到文件上传名
        String filename=part.getSubmittedFileName();
        System.out.println(&quot;filename&quot;+filename);
        //得到文件存放的路径
        String filePath = request.getServletContext().getRealPath(&quot;/&quot;);

        System.out.println(&quot;文件存放的路径：&quot;+ filePath);
        //上次文件到指定目录
        part.write(filePath+&quot;/&quot;+filename);
    &#125;
&#125;
</code></pre>
<h3 id="文件下载"><a href="#文件下载" class="headerlink" title="文件下载"></a>文件下载</h3><h4 id="超链接下载"><a href="#超链接下载" class="headerlink" title="超链接下载"></a>超链接下载</h4><p>当我们在HTML或JSP页面中使用a标签时，原意是希望能够进行跳转，但当超链接遇到浏览器不识别的资源时会自动下载;当遇见浏览器能够直接显示的资源，浏览器就会默认显示出来，比如txt、png、jpg等。当然我们也可以通过download 属性规定浏览器进行下载。但有些浏览器并不支持。</p>
<ul>
<li><p>默认下载</p>
<pre><code class="html">&lt;!--当超链接遇到浏览器不识别的资源时，会自动下载--&gt;
&lt;a href=&quot;test.zip&quot;&gt;超链接下载&lt;/ a&gt;
</code></pre>
</li>
<li><p>指定download 属性下载</p>
<pre><code class="html">&lt;!--当超链接遇到浏览器识别的资源时，默认不会下载。通过download属性可进行下载--&gt;
&lt;a href=&quot;test.txt&quot; down1oad&gt;超链接下载&lt;/ a&gt;
</code></pre>
<p>download属性可以不写任何信息，会自动使用默认文件名。如果设置了download属性的值，则使用设置的值做为文件名。当用户打开浏览器点击链接的时候就会直接下载文件。</p>
</li>
</ul>
<h4 id="后台实现下载"><a href="#后台实现下载" class="headerlink" title="后台实现下载"></a>后台实现下载</h4><ul>
<li>实现步骤<ol>
<li>需要通过<code>response.setContentType</code>方法设置<code>Content-type</code>头字段的值，为浏览器无法使用某种方式或激活某个程序来处理的MIME类型，例如<code>&quot;application/octet-stream&quot;</code>或<code>&quot;application/x-msdownload&quot;</code>等。</li>
<li>需要通过<code>response.setHeader</code>方法设置<code>Content-Disposition</code>头的值为<code>&quot;attachmentfilename=文件名&quot;</code></li>
<li>读取下载文件，调用<code>response.getOutputStream</code>方法向客户端写入附件内容。</li>
</ol>
</li>
</ul>
<pre><code class="html">&lt;form action=&quot;downdload&quot; &gt;
    文件名：&lt;input type=&quot;text&quot; name=&quot;fileName&quot; placeholder=&quot;请输入文件信息&quot;&gt;
    &lt;button&gt;下载&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<p>在web文件夹里新建了个download文件夹，将可下载的文件放在download文件夹里</p>
<pre><code class="java">package Context;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@WebServlet(&quot;/downdload&quot;)
public class donmlode extends HttpServlet &#123;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
        request.setCharacterEncoding(&quot;UTF-8&quot;);
        response.setContentType(&quot;text/html;charset=UTF-8&quot;);
        //获取参数（文件名）
        String fileName = request.getParameter(&quot;fileName&quot;);
        //非空判断  trim():去除字符前后的空格
        if(fileName == null || &quot;&quot;.equals(fileName.trim()))&#123;
            response.getWriter().write(&quot;请输入要下载的文件名&quot;);
            response.getWriter().close();
            return;
        &#125;
        //获取图片存放的位置
        String path =request.getServletContext().getRealPath(&quot;/download/&quot;);
        //通过路径得到一个file对象
        File file = new File(path+fileName);
        //判断文件是否存在并且是个标准文件
        if(file.exists()&amp;&amp;file.isFile())&#123;
            //设置响应类型（浏览器无法使用某种方式或激活某个程序来处理的 MIME类型
            response.setContentType(&quot;application/x-msdownload&quot;);
            //设置响应头
            response.setHeader(&quot;Content-Disposition&quot;,&quot;attachment;filename=&quot; + fileName);
            //得到file文件输入流
            InputStream in = new FileInputStream(file);
            //得到字节输出流
            ServletOutputStream out =response.getOutputStream();
            //定义byte数组
            byte[] bytes = new byte[1024];
            //定义数组
            int len=0;
            //循环输出
            while((len = in.read(bytes)) != -1)&#123;
                //输出
                out.write(bytes,0,len);
            &#125;
            //关闭资源
            out.close();
            in.close();
        &#125;else &#123;
            response.getWriter().write(&quot;文件不存在，请重试&quot;);
            response.getWriter().close();
        &#125;
    &#125;
&#125;
</code></pre>
<blockquote>
<p>注：需要下载的文件的文件名不能以数字开头否则找不到文件</p>
</blockquote>

  </article>

  
    
  <div class="nexmoe-post-copyright">
    <strong>本文作者：</strong>lingqu<br>
    <strong>本文链接：</strong><a href="https://lingqu.github.io/2021/06/10/Servlet/" title="https:&#x2F;&#x2F;lingqu.github.io&#x2F;2021&#x2F;06&#x2F;10&#x2F;Servlet&#x2F;" target="_blank" rel="noopener">https:&#x2F;&#x2F;lingqu.github.io&#x2F;2021&#x2F;06&#x2F;10&#x2F;Servlet&#x2F;</a><br>
    
      <strong>版权声明：</strong>本文采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/cn/deed.zh" target="_blank">CC BY-NC-SA 3.0 CN</a> 协议进行许可
    
  </div>


  
  
  <div class="nexmoe-post-meta nexmoe-rainbow">
    
    
</div>

  <div class="nexmoe-post-footer">
    <section class="nexmoe-comment">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1.5.0/dist/gitalk.min.css">
<div id="gitalk"></div>
<script src="https://cdn.jsdelivr.net/npm/gitalk@1.5.0/dist/gitalk.min.js"></script>
<script type="text/javascript">
    var gitalk = new Gitalk({
        clientID: '80b2453b6d5f37ad6225',
        clientSecret: '43e99fa852795c9a7b3eb924b2558c64b84bbdeb',
        id: window.location.pathname,
        repo: 'nexmoe.github.io',
        owner: 'nexmoe',
        admin: 'nexmoe'
    })
    gitalk.render('gitalk')
</script>
</section>
  </div>
</div>
        <div class="nexmoe-post-right">
          <div class="nexmoe-fixed">
            <div class="nexmoe-tool"> 
              
                
              
              <a href="#nexmoe-content" class="toc-link" aria-label="回到顶部" title="top"><button class="mdui-fab mdui-ripple"><i class="nexmoefont icon-caret-top"></i></button></a>
            </div>
          </div>
        </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/combine/npm/lazysizes@5.1.0/lazysizes.min.js,gh/highlightjs/cdn-release@9.15.8/build/highlight.min.js,npm/mdui@0.4.3/dist/js/mdui.min.js?v=1"></script>
<script>
	hljs.initHighlightingOnLoad();
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>


<script src="https://cdn.jsdelivr.net/gh/xtaodada/xtaodada.github.io@0.0.2/copy.js"></script>
 

<script src="/js/app.js?v=1629344957172"></script>

<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.8.1/dist/js/jquery.justifiedGallery.min.js"></script>
<script>
	$(".justified-gallery").justifiedGallery({
		rowHeight: 160,
		margins: 10,
	});
</script>

  





</body>

</html>
